/**
 * $RCSfile: sqlplus.js,v $$
 * $Revision: 1.1 $
 * $Date: 2012-10-18 $
 *
 * Copyright (C) 2008 Skin, Inc. All rights reserved.
 * This software is the proprietary information of Skin, Inc.
 * Use is subject to license terms.
 * @author xuesong.net
 */
(function() {
    var HtmlUtil = {};
    HtmlUtil.replacement = {
        "<": "&lt;",
        ">": "&gt;",
        "\"": "&quot;",
        " ": "&nbsp;",
        "\u00ae": "&reg;",
        "\u00a9": "&copy;"
    };

    HtmlUtil.replace = function(e){return HtmlUtil.replacement[e];};

    HtmlUtil.encode = function(source, crlf){
        if(source == null) {
            return "";
        }

        if(crlf == null) {
            crlf = "<br/>";
        }
        return source.toString().replace(new RegExp("[<>\"\\u00ae\\u00a9]", "g"), HtmlUtil.replace).replace(new RegExp("\\r?\\n", "g"), crlf);
    };

    var TextPanel = {};
    TextPanel.open = function(content) {
        var container = document.getElementById("content-panel");

        if(container == null) {
            var buffer = [];
            buffer[buffer.length] = "<div class=\"panel\">";
            buffer[buffer.length] = "<div class=\"panel-title\" dragable=\"true\">";
            buffer[buffer.length] = "<h4>Alter Sql</h4>";
            buffer[buffer.length] = "<span class=\"close\"></span>";
            buffer[buffer.length] = "</div>";
            buffer[buffer.length] = "<div class=\"panel-content\" style=\"margin: 0px; padding: 0px; width: 800px; overflow: hidden; cursor: default;\">";
            buffer[buffer.length] = "<textarea name=\"__content__\" style=\"display: block; margin: 0px; padding: 0px; width: 798px; height: 244px; outline: none; resize: none; overflow: scroll;\"></textarea>";
            buffer[buffer.length] = "<div class=\"operator\">";
            buffer[buffer.length] = "<input type=\"button\" class=\"button cancel\" value=\"关 闭\"/>";
            buffer[buffer.length] = "</div>";
            buffer[buffer.length] = "</div>";
            buffer[buffer.length] = "</div>";

            var container = document.createElement("div");
            container.id = "content-panel"
            container.className = "dialog hide";
            container.style.position = "absolute";
            container.style.top = "70px";
            container.style.left = "20px";
            container.innerHTML = buffer.join("");
            document.body.appendChild(container);

            jQuery(container).find("input.cancel").click(function() {
                jQuery("#content-panel").hide();
            });

            jQuery(container).find("div.panel-title span.close").click(function() {
                jQuery("#content-panel").hide();
            });
            Dragable.registe(container);
        }
        jQuery(container).find("textarea[name=__content__]").val(content);
        jQuery(container).show();
    };

    var SqlPlus = {};

    SqlPlus.list = function(container, columns, records) {
        var columnCount = columns.length
        var table = document.createElement("table");
        var head = table.insertRow(-1);

        var td = head.insertCell(-1);
        td.innerHTML = "&nbsp;";

        for(var i = 0; i < columnCount; i++) {
            var td = head.insertCell(-1);
            td.innerHTML = HtmlUtil.encode(columns[i].columnName);
        }

        for(var i = 0; i < records.length; i++) {
            var tr = table.insertRow(-1);
            var values = records[i].values;

            var td = tr.insertCell(-1);
            td.innerHTML = HtmlUtil.encode(i + 1);

            for(var j = 0; j < columnCount; j++) {
                var td = tr.insertCell(-1);
                var column = columns[j];
                td.style.cursor = "default";
                SqlPlus.setValue(td, column.typeName, values[j]);
            }
        }

        table.className = "data-grid";
        head.className = "thead";
        container.appendChild(table);
    };

    SqlPlus.setValue = function(e, columnType, value) {
        e.setAttribute("column-type", columnType);
        e.setAttribute("column-value", value);

        jQuery(e).dblclick(function() {
            TextPanel.open(this.getAttribute("column-value"));
            return false;
        });

        if(value == null || value == undefined) {
            e.appendChild(document.createTextNode("NULL"));
            return;
        }

        if(typeof(value) != "number") {
            e.appendChild(document.createTextNode(value));
            return;
        }

        if(columnType == "DATETIME" || columnType == "TIMESTAMP" || columnType == "DATE" || columnType == "TIME") {
            var content = SqlPlus.getDateTime(value);
            e.appendChild(document.createTextNode(content));
            return;
        }
        else {
            e.appendChild(document.createTextNode(value));
            return;
        }
    };

    SqlPlus.getValue = function(dataTypeName, value, escape) {
        if(value == null) {
            return "NULL";
        }

        if(typeof(value) != "number") {
            if(escape) {
                return HtmlUtil.encode(value);
            }
            else {
                return value;
            }
        }

        if(dataTypeName == "DATETIME" || dataTypeName == "TIMESTAMP" || dataTypeName == "DATE" || dataTypeName == "TIME") {
            return SqlPlus.getDateTime(value);
        }
        else {
            if(escape) {
                return HtmlUtil.encode(value);
            }
            else {
                return value;
            }
        }
    };

    SqlPlus.getDateTime = function(date){
        if(date == null) {
            date = new Date();
        }

        if(typeof(date) == "number") {
            var d = new Date();
            d.setTime(date);
            date = d;
        }

        var y = date.getFullYear();
        var M = date.getMonth() + 1;
        var d = date.getDate();
        var h = date.getHours();
        var m = date.getMinutes();
        var s = date.getSeconds();
        var S = date.getTime() % 1000;

        var a = [];

        a[a.length] = y.toString();
        a[a.length] = "-";

        if(M < 10) {
            a[a.length] = "0";
        }

        a[a.length] = M.toString();
        a[a.length] = "-";

        if(d < 10) {
            a[a.length] = "0";
        }

        a[a.length] = d.toString();
        a[a.length] = " ";

        if(h < 10) {
            a[a.length] = "0";
        }

        a[a.length] = h.toString();
        a[a.length] = ":";

        if(m < 10) {
            a[a.length] = "0";
        }

        a[a.length] = m.toString();
        a[a.length] = ":";

        if(s < 10) {
            a[a.length] = "0";
        }

        a[a.length] = s.toString();
        a[a.length] = " ";

        if(S < 100) {
            a[a.length] = "0";
        }

        if(S < 10) {
            a[a.length] = "0";
        }

        a[a.length] = S.toString();
        return a.join("");
    };

    SqlPlus.getText = function(e) {
        var b = [];
        var list = e.childNodes;
        var length = list.length;

        for(var i = 0; i < length; i++) {
            var node = list[i];
            var nodeType = node.nodeType;
            var nodeName = node.nodeName.toLowerCase();

            if(node.nodeType == 1) {
                if(nodeName == "p" || nodeName == "div" || nodeName == "br") {
                    b[b.length] = "\r\n";

                    if(node.childNodes.length > 0) {
                        b[b.length] = this.getText(node);
                        b[b.length] = "\r\n";
                    }
                }
                else {
                    if(node.childNodes.length > 0) {
                        b[b.length] = this.getText(node);
                    }
                }
            }
            else if(node.nodeType == 3) {
                b[b.length] = node.nodeValue;
            }
        }
        return b.join("").replace(/[\u00a0]/g, " ").replace(/[\r\n]+/g, "\r\n");
    };

    SqlPlus.setMessage = function(c, message) {
        var div = document.createElement("div");
        var pre = document.createElement("pre");
        div.style.padding = "6px";
        pre.appendChild(document.createTextNode(message));
        div.appendChild(pre);
        c.appendChild(div);
    };
    window.SqlPlus = SqlPlus;
    window.DomUtil = DomUtil;
})();

(function() {
    var getCodeMirrorTheme = function() {
        var css = null;
        var list = document.getElementsByTagName("link");

        for(var i = 0, length = list.length; i < length; i++) {
            var src = list[i].href;


            if(src != null && src != undefined && src.length > 0) {
                var k = src.indexOf("/theme/");

                if(src.indexOf("/codemirror") > -1 && k > -1) {
                    css = src.substring(k + 7);
                    break;
                }
            }
        }
        return (css != null ? css.replace(".css", "") : "unknown");
    };

    var SqlPlusPanel = com.skin.framework.Class.create(TabPanel);

    SqlPlusPanel.prototype.add = function(sql) {
        var buffer = [];
        buffer[buffer.length] = "<div class=\"menu-bar\">";
        buffer[buffer.length] = "    <a class=\"button run\" href=\"javascript:void(0)\"><span class=\"run\"></span>run</a>";
        buffer[buffer.length] = "</div>";
        buffer[buffer.length] = "<div class=\"split-panel resize-d\">";
        buffer[buffer.length] = "    <div class=\"split-left sql-editor\" style=\"height: 400px; overflow: hidden;\"></div>";
        buffer[buffer.length] = "    <div class=\"split-bar\"></div>";
        buffer[buffer.length] = "    <div class=\"split-right\">";
        buffer[buffer.length] = "        <div class=\"tab-label-wrap\">";
        buffer[buffer.length] = "            <ul>";
        buffer[buffer.length] = "                <li class=\"tab-label tab-active\"><span class=\"label\">Message</span></li>";
        buffer[buffer.length] = "                <li class=\"tab-label\"><span class=\"label\">Result</span></li>";
        buffer[buffer.length] = "            </ul>";
        buffer[buffer.length] = "        </div>";
        buffer[buffer.length] = "        <div class=\"tab-panel-wrap resize-d\">";
        buffer[buffer.length] = "            <div class=\"tab-panel resize-d result-msg\" style=\"display: block;\"></div>";
        buffer[buffer.length] = "            <div class=\"tab-panel resize-d result-set\"></div>";
        buffer[buffer.length] = "        </div>";
        buffer[buffer.length] = "    </div>";
        buffer[buffer.length] = "</div>";

        var title = null;
        var database = PageContext.getAttribute("database");

        if(database != null) {
            title = "SQL [" + database + "]";
        }
        else {
            title = "SQL [Query]";
        }

        var panel = this.append({"title": title, "closeable": true, "content": buffer.join("")});
        var parent = jQuery(panel);

        /**
         * sub tab panel
         */
        new TabPanel({"container": parent.find("div.split-right").get(0)});

        parent.find("div.split-panel").each(function() {
            new SplitPanel({"container": this});
        });

        parent.find(".sql-editor").css("padding", "0px");
        var cmTheme = getCodeMirrorTheme();
        var sqlEditor = CodeMirror(parent.find(".sql-editor").get(0), {
            "mode": "text/x-mysql",
            "lineNumbers": true,
            "indentUnit": 4,
            "lineSeparator": "\r\n",
            "theme": cmTheme,
            "value": (sql || "select * from xxx;\r\n\r\n\r\n\r\n\r\n\r\n")
        });

        /**
         * 加入到自动更新高度的事件中
         */
        parent.find(".sql-editor").children(".CodeMirror").addClass("auto-height");
        jQuery(window).trigger("resize");

        parent.find("a.run").click(function() {
            var src = jQuery(this);
            var disabled = src.attr("disabled");

            if(disabled == true || disabled == "true" || disabled == "disabled") {
                return;
            }

            src.attr("disabled", true);
            src.find("span").attr("class", "loading");

            var editor = src.closest("div.tab-panel").find(".sql-editor");
            var connectionName = PageContext.getAttribute("connectionName");
            var database = PageContext.getAttribute("database");
            var resultMsg = src.closest("div.tab-panel").find("div.result-msg");
            var resultSet = src.closest("div.tab-panel").find("div.result-set");

            resultMsg.html("");
            resultSet.html("");

            var params = {};
            params.name = connectionName;
            params.database = database;
            params.sql = jQuery.trim(sqlEditor.getSelection());

            if(params.sql.length < 1) {
                params.sql = jQuery.trim(sqlEditor.getValue());
            }

            jQuery.ajax({
                "type": "post",
                "url": PageContext.getContextPath() + "/webcat/sqlplus/execute.html",
                "data": jQuery.param(params, true),
                "dataType": "json",
                "error": function() {
                    src.attr("disabled", false);
                    src.find("span").attr("class", "run");
                },
                "success": function(result) {
                    src.attr("disabled", false);
                    src.find("span").attr("class", "run");
                    src.closest("div.tab-panel").find("div.tab-label-wrap ul li:eq(0)").click();

                    if(result == null) {
                        resultMsg.html("系统错误，请稍后再试！");
                        return;
                    }

                    SqlPlus.setMessage(resultMsg.get(0), result.message);

                    if(result.columns != null) {
                        SqlPlus.list(resultSet.get(0), result.columns, result.records);
                        src.closest("div.tab-panel").find("div.tab-label-wrap ul li:eq(1)").click();
                        resultSet.change();
                    }
                }
            });
        });
    };
    window.SqlPlusPanel = SqlPlusPanel;
})();

var TextEditor = function(editor) {
    var self = this;
    this.editor = editor;

    DomUtil.addListener(editor, "paste", function(event) {
        var clipboard = event.clipboardData;
        var content = clipboard.getData("text/plain");

        if(content != null) {
            this.innerHTML = Sql.highlight(content);
        }
        return DomUtil.stop(event);
    }, false);
};

TextEditor.prototype.getDocument = function() {
    return window.document;
};

TextEditor.prototype.getEditor = function() {
    return this.editor;
};

TextEditor.prototype.setText = function(text) {
    this.editor.innerHTML = this.highlight(text);
};

TextEditor.prototype.getText = function() {
    return jQuery(this.editor).text();
};

TextEditor.prototype.highlight = function(text) {
    return text;
};

TextEditor.prototype.paste = function(){
    try{
        this.setBookmark();
        var doc = this.getDocument();
        if(doc.execCommand("paste"), !doc.queryCommandSupported("paste")){
            throw {"name": "UnsupportOperation", "message": "UnsupportOperation"};
        }
    }
    catch(e){
        console.log(e.name + ": " + e.message);
    }
};

TextEditor.prototype.exec = function(c, t, a){
    this.setBookmark();
    this.getDocument().execCommand(c, t, a);
};

TextEditor.prototype.focus = function(){
    this.getEditor().focus();
};

TextEditor.prototype.getSelection = function() {
    return (document.selection ? document.selection : window.getSelection());
};

TextEditor.prototype.getRange = function(){
    var selection = this.getSelection();

    if(selection.createRange) {
        return selection.createRange();
    }
    else if(selection.createTextRange) {
        return selection.createTextRange();
    }
    return null;
};

TextEditor.prototype.getBookmark = function(){
    this.focus();
    var range = this.getRange();

    if(range != null) {
        range = (range.cloneRange ? range.cloneRange() : range);
        var w = this.getWindow();
        return (this.bookmark = {top: w.scrollTop, range: range});
    }
    return null;
};

TextEditor.prototype.setBookmark = function() {
    if(this.bookmark != null) {
        var range = this.bookmark.range;
        if(this.IE) {
            range.select();
        }
        else {
            var s = this.getSelection();
            s.removeAllRanges(),
            s.addRange(range);
        }
        this.getEditor().scrollTop = this.bookmark.top;
        this.bookmark = null;
    }
    else {
        this.focus();
    }
};

var Sql = {};
Sql.keywords = ["select", "insert", "create", "update", "delete", "from",
    "drop", "primary", "key", "table", "view", "alter", "execute",
    "from", "where", "and", "or", "order", "by", "group", "having",
    "join", "inner", "left", "right", "union",
    "auto_increment", "comment", "is", "not", "default",
    "add", "modify", "change", "unique", "index", "using", "btree", "hash", "fulltext"];

Sql.trim = function(s) {
    return (s != null ? s.toString().replace(/(^\s*)|(\s*$)/g, "") : "");
};
Sql.startsWith = function(source, prefix) {
    return (source.length >= prefix.length && source.substring(0, prefix.length) == prefix);
};
Sql.getPattern = function() {
    if(this.pattern == null) {
        var es = [
            /* 单行注释  */   "(--[\\s\\S]*?\n)"
            /* 多行注释  */ , "(\\/\\/.*|\\/\\*[\\s\\S]*?\\*\\/)"
            /* 字符串    */ , "(\"(?:[^\"\\\\]|\\\\[\\s\\S])*\"|'(?:[^'\\\\]|\\\\[\\s\\S])*')"
            /* 常量      */ , "\\b(true|false|null|undefined|NaN)\\b"
            /* 关键字    */ , "\\b(" + this.keywords.join("|") + ")\\b"
            /* 内置对象  */ , "\\b(int|tinyint|smallint|mediumint|bigint|boolean|float|double|decimal|char|varchar|binary|varbinary|text|mediumtext|longtext|date|datetime|timestamp|time|year|clob|blob|longblob|unsigned)\\b"
            /* 变量      */ , "(?:[^\\W\\d]|\\$)[\\$\\w]*"
            /* 数字      */ , "(0[xX][0-9a-fA-F]+|\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?|\\.\\d+(?:[eE][+-]?\\d+)?)"
        ];
        this.pattern = es.join("|");
    }
    return this.pattern;
};

Sql.highlight = function(sql) {
    if(sql == null) {
        return "";
    }

    var pattern = this.getPattern();
    var regexp = new RegExp(pattern, "gi");
    var result = sql.replace(regexp, function() {
        var s = null;
        var a = arguments;

        for(var i = 1; i < a.length; i++) {
            s = a[i];

            if(s != null && s != undefined) {
                switch(i) {
                    case 1:
                        return "<span class=\"comment\">" + s + "</span>";
                    case 2:
                        return "<span class=\"comment\">" + s + "</span>";
                    case 3:
                        return "<span class=\"string\">" + s + "</span>";
                    case 4:
                        return "<span class=\"atom\">" + s + "</span>";
                    case 5:
                        return "<span class=\"keyword\">" + s + "</span>";
                    case 6:
                        return "<span class=\"builtin\">" + s + "</span>";
                    case 7:
                        return "<span class=\"number\">" + s + "</span>";
                    default: {
                        return a[0];
                    }
                }
            }
        }
        return "";
    });
    return result;
};

var AlterPanel = {};

AlterPanel.setEnabled = function(enabled) {
    if(enabled == true) {
        jQuery("#alter-panel input.ensure").removeClass("disabled").prop("disabled", false);
    }
    else {
        jQuery("#alter-panel input.ensure").addClass("disabled").prop("disabled", true);
    }
};

AlterPanel.loading = function() {
    var content = "<div><img src=\"" + PageContext.getContextPath() + "/resource/webcat/images/loading.gif\"/></div>"
        + "<div style=\"padding-top: 6px; font-size: 12px; line-height: 20px; color: #ff0000;\">正在生成执行任务，请稍候...</div>";

    jQuery("#alter-panel .sql-editor").css("cursor", "wait").html(content);
    jQuery("#alter-panel input.cancel").val("取 消");
    jQuery("#alter-panel input.ensure").addClass("disabled").prop("disabled", true);
    jQuery("#alter-panel input.ensure").show();
    jQuery("#alter-panel").show();
};

AlterPanel.running = function() {
    var content = "<div><img src=\"" + PageContext.getContextPath() + "/resource/webcat/images/loading.gif\"/></div>"
        + "<div style=\"padding-top: 6px; font-size: 12px; line-height: 20px; color: #ff0000;\">正在执行变更，请稍候...</div>";

    jQuery("#alter-panel .sql-editor").css("cursor", "wait").html(content);
    jQuery("#alter-panel input.cancel").val("关 闭");
    jQuery("#alter-panel input.cancel").addClass("disabled").prop("disabled", true);
    jQuery("#alter-panel input.ensure").hide();
    jQuery("#alter-panel").show();
};

AlterPanel.error = function(message) {
    jQuery("#alter-panel .sql-editor").css("cursor", "default").html("<div class=\"error\"><p>Error: " + message + "</p></div>");
    jQuery("#alter-panel input.ensure").hide();
    jQuery("#alter-panel input.cancel").val("关 闭");
    jQuery("#alter-panel").show();
};

AlterPanel.show = function(content) {
    jQuery("#alter-panel .sql-editor").css("cursor", "default").html(content);
    jQuery("#alter-panel input.ensure").hide();
    jQuery("#alter-panel input.cancel").removeClass("disabled").prop("disabled", false).val("关 闭");
    jQuery("#alter-panel").show();
};

AlterPanel.submit = function(content) {
    jQuery("#alter-panel input.ensure").val("执 行").show();
    jQuery("#alter-panel input.cancel").val("取 消").show();
    jQuery("#alter-panel .sql-editor").css("cursor", "default").html(content);
    jQuery("#alter-panel").show();
};

var SqlParsePanel = function() {
    this.containerId = "sql-create-panel";
    this.init();
};

SqlParsePanel.prototype.init = function() {
    var self = this;
    var container = this.getContainer();
    Dragable.registe("sql-create-panel");

    /**
     * jQuery的paste事件存在bug，无法获取clipboardData
     */
    DomUtil.addListener(jQuery(this.getContainer()).find(".sql-editor").get(0), "paste", function(event) {
        var clipboard = event.clipboardData;
        var content = clipboard.getData("text/plain");

        if(content != null) {
            self.setHtml(Sql.highlight(content));
        }
        return DomUtil.stop(event);
    }, false);

    jQuery(container).find("input.ensure").click(function() {
        self.callback(self.getText());
    });

    jQuery(container).find("input.cancel").click(function() {
        self.close();
    });
};

SqlParsePanel.prototype.error = function(message) {
    this.open("<div class=\"error\"><p>Error: " + message + "</p></div>");
};

SqlParsePanel.prototype.open = function(html) {
    if(html != null) {
        this.setHtml(html);
    }
    else {
        this.setHtml("");
    }
    jQuery(this.getContainer()).show();
    jQuery(this.getContainer()).find(".sql-editor").focus();
};

SqlParsePanel.prototype.close = function() {
    jQuery(this.getContainer()).hide();
};

SqlParsePanel.prototype.setHtml = function(html) {
    jQuery(this.getContainer()).find(".sql-editor").html(html);
};

SqlParsePanel.prototype.getText = function() {
    return jQuery(this.getContainer()).find(".sql-editor").text();
};

SqlParsePanel.prototype.select = function() {
    DomUtil.select(jQuery(this.getContainer()).find(".sql-editor").get(0));
};

SqlParsePanel.prototype.callback = function() {
};

SqlParsePanel.prototype.getContainer = function() {
    return document.getElementById(this.containerId);
};

jQuery(function() {
    if(jQuery("#sqlplus-panel").size() > 0) {
        var tableName = PageContext.getAttribute("tableName");
        var sqlPlusPanel = new SqlPlusPanel({"container": "sqlplus-panel"});
        sqlPlusPanel.add("select * from " + tableName);
        sqlPlusPanel.add("select * from " + tableName);
        sqlPlusPanel.add("select * from " + tableName);
        sqlPlusPanel.add("select * from " + tableName);
        sqlPlusPanel.active(0);
    }
});
